package sse.controller;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.time.Duration;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/stream")
public class ChatController {

    @GetMapping("/sse")
    public Flux<ServerSentEvent<String>> streamSse() {
//        return Flux.interval(Duration.ofSeconds(1))
        return Flux.range(0, 20)
                .delayElements(Duration.ofSeconds(1))
                .map(sequence -> ServerSentEvent.<String>builder()
                        .id(String.valueOf(sequence))
                        .event("periodic-event")
                        .data("Current time: " + LocalTime.now())
                        .build());

    }

    @PostMapping(value = "/simple", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> simpleSse() {
        return Flux.interval(Duration.ofSeconds(1)).map(sequence -> "Current time: " + LocalTime.now());
    }


    @PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> streamChat() {

        List<String> responses = mockModelResponse();
        AtomicLong counter = new AtomicLong();

        return Flux.fromIterable(responses)
                .delayElements(Duration.ofSeconds(3))
                .map(sequence -> ServerSentEvent.<String>builder()
                        .id(String.valueOf(counter.getAndIncrement()))
                        .event("data-event")
                        .data(sequence)
                        .build());
    }

    private List<String> mockModelResponse() {
        List<String> c = new ArrayList<>();
        c.add("三国演义是中国古代四大名著之一。");
        c.add("它讲述了东汉末年群雄割据的故事。");
        c.add("主要人物包括刘备、关羽、张飞、曹操、孙权等。");
        return c;
    }


    @PostMapping(value = "/laozi", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<String>> streamLaoZi() throws IOException {
        File file = Paths.get("D:", "workspace", "java", "spring5-rest-test", "server", "src", "test", "resources", "道德经.md")
                .toFile();
        List<String> responses = FileUtils.readLines(file, StandardCharsets.UTF_8)
                .stream()
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());

        return Flux.fromIterable(responses)
                .delayElements(Duration.ofSeconds(3))
                .map(sequence -> ServerSentEvent.<String>builder().event("data-event").data(sequence).build());
    }
}
